package com.regulareport.form.service.impl;

import java.io.*;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.regulareport.common.config.RuoYiConfig;
import com.regulareport.common.core.domain.entity.ReportFormsEdit;
import com.regulareport.common.core.redis.RedisCache;
import com.regulareport.common.utils.StringUtils;
import com.regulareport.common.utils.file.FileUploadUtils;
import com.regulareport.common.utils.file.FileUtils;
import com.regulareport.common.utils.poi.ExcelToJsonConverter;
import com.regulareport.form.domain.ReportFormsEditVO;
import com.regulareport.form.mapper.ReportFormsEditMapper;
import com.regulareport.form.service.IReportFormsEditService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

/**
 * 报版本管理Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-09-03
 */
@Service
public class ReportFormsEditServiceImpl implements IReportFormsEditService
{
    private static final Logger log = LoggerFactory.getLogger(ReportFormsEditServiceImpl.class);
    @Autowired
    private ReportFormsEditMapper reportFormsEditMapper;

    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    @Autowired
    private RedisCache redisCache;

    @Value("${token.expireTime}")
    private int expireTime;

    /**
     * 查询报版本管理
     * 
     * @param pkId 报版本管理主键
     * @return 报版本管理
     */
    @Override
    public ReportFormsEditVO selectReportFormsEditByPkId(Long pkId) throws Exception
    {

        String excelJson = "";
        ReportFormsEdit reportFormsEdit = reportFormsEditMapper.selectReportFormsEditByPkId(pkId);
        String edition = reportFormsEdit.getEdition();
        String reportFormNo = reportFormsEdit.getReportFormNo();
        excelJson = redisCache.getCacheObject( reportFormNo + "_" + edition);
        //缓存不存在，从数据库获取报表信息解析
        if(StringUtils.isEmpty(excelJson)){
            excelJson = ExcelToJsonConverter.convertByteArrayWithInputStream(reportFormsEdit.getFileJson());;
            redisCache.setCacheObject( reportFormsEdit.getReportFormNo() + "_" + reportFormsEdit.getEdition(), excelJson, expireTime, TimeUnit.DAYS);
        }
        ReportFormsEditVO reportFormsEditVO = new ReportFormsEditVO();
        reportFormsEditVO.setPkId(reportFormsEdit.getPkId());
        reportFormsEditVO.setReportFormNo(reportFormsEdit.getReportFormNo());
        reportFormsEditVO.setReportFormName(reportFormsEdit.getReportFormName());
        reportFormsEditVO.setFileJson(excelJson);
        reportFormsEditVO.setFilePath(reportFormsEdit.getFilePath());
        return reportFormsEditVO;
    }

    /**
     * 查询报版本管理列表
     * 
     * @param reportFormsEdit 报版本管理
     * @return 报版本管理
     */
    @Override
    public List<ReportFormsEdit> selectReportFormsEditList(ReportFormsEdit reportFormsEdit)
    {
        return reportFormsEditMapper.selectReportFormsEditList(reportFormsEdit);
    }

    /**
     * 新增报版本管理
     * 
     * @param reportFormsEdit 报版本管理
     * @return 结果
     */
    @Override
    public int insertReportFormsEdit(ReportFormsEdit reportFormsEdit)
    {
        return reportFormsEditMapper.insertReportFormsEdit(reportFormsEdit);
    }

    /**
     * 修改报版本管理
     * 
     * @param reportFormsEdit 报版本管理
     * @return 结果
     */
    @Override
    public int updateReportFormsEdit(ReportFormsEdit reportFormsEdit)
    {
        return reportFormsEditMapper.updateReportFormsEdit(reportFormsEdit);
    }

    /**
     * 批量删除报版本管理
     * 
     * @param pkIds 需要删除的报版本管理主键
     * @return 结果
     */
    @Override
    public int deleteReportFormsEditByPkIds(Long[] pkIds)
    {
        return reportFormsEditMapper.deleteReportFormsEditByPkIds(pkIds);
    }

    /**
     * 删除报版本管理信息
     * 
     * @param pkId 报版本管理主键
     * @return 结果
     */
    @Override
    public int deleteReportFormsEditByPkId(Long pkId)
    {
        ReportFormsEdit reportForms = reportFormsEditMapper.selectReportFormsEditByPkId(pkId);
        File desc = new File(RuoYiConfig.getProfile() + File.separator + reportForms.getFilePath());
        FileUtils.deleteFile(desc.getAbsolutePath());

        return reportFormsEditMapper.deleteReportFormsEditByPkId(pkId);
    }

    /**
     * 上传银监模板信息
     * @param file
     * @param fillFile 填报说明附件
     * @param reportFormsEdit
     * @return
     */
    @Override
    public int uploadReportFormsEdit(MultipartFile file, MultipartFile fillFile, ReportFormsEdit reportFormsEdit) throws Exception{

        //解析excel模板为byte数组
        byte[] fileBytes = null;
        try {
            fileBytes = file.getBytes();
        } catch (Exception e) {
            log.error("文件模板转换失败", e);
            //物理删除文件信息项
            reportFormsEditMapper.deleteReportFormsEditByPkId(reportFormsEdit.getPkId());
            //转换模板失败
            throw new Exception("文件模板转换失败");
        }
        if(fileBytes == null){
            throw new Exception("文件模板无内容");
        }
        reportFormsEdit.setFileJson(fileBytes);

        String uploadDir = RuoYiConfig.getUploadPath() + "/" + reportFormsEdit.getEdition();
        String filePath = "";
        try {
            filePath = FileUploadUtils.uploadOriginalFile(uploadDir, file);
            log.info("银监模板{}，上传服务器成功", filePath);
        } catch (Exception e) {
            reportFormsEditMapper.deleteReportFormsEditByPkId(reportFormsEdit.getPkId());
            throw new Exception("模板上传服务器失败");
        }
        if(fillFile != null) {
            //填报说明附件上传   D:/ruoyi/uploadPath/upload/2025/fillInstruct
            String uploadDirFill = RuoYiConfig.getUploadPath() + "/" + reportFormsEdit.getEdition() + "/" + "fillInstruct";
            String fillFilePath = "";
            try {
                fillFilePath = FileUploadUtils.uploadOriginalFile(uploadDirFill, fillFile);
                log.info("银监{}模板，填报说明{}，上传服务器成功", reportFormsEdit.getPkId(), fillFilePath);
            } catch (Exception e) {
                reportFormsEditMapper.deleteReportFormsEditByPkId(reportFormsEdit.getPkId());
                throw new Exception("填报说明附件上传服务器失败");
            }
            String fillFileName = fillFile.getOriginalFilename();
            reportFormsEdit.setFillFileName(fillFileName);
            reportFormsEdit.setFillFilePath(fillFilePath);
        }

        redisCache.deleteObject(reportFormsEdit.getReportFormNo() + "_" + reportFormsEdit.getEdition());

        String fileName = file.getOriginalFilename();
        reportFormsEdit.setFileName(fileName);
        reportFormsEdit.setFilePath(filePath);
        reportFormsEdit.setFileJson(fileBytes);
        int resultNum = reportFormsEditMapper.updateReportFormsEdit(reportFormsEdit);

        //异步解析银监模板到缓存
        taskExecutor.execute(() -> {
            System.out.println(Thread.currentThread().getName() + " 执行任务: " + reportFormsEdit.getReportFormNo() + "_" + reportFormsEdit.getEdition());
            String excelJson = "";
            InputStream input = null;
            try {
                byte[] fileJsonArr = reportFormsEdit.getFileJson();
                input = new ByteArrayInputStream(fileJsonArr);
                excelJson = ExcelToJsonConverter.convertExcelWithStyles(input);
                input.close();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    input.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            redisCache.setCacheObject(reportFormsEdit.getReportFormNo() + "_" + reportFormsEdit.getEdition(), excelJson, expireTime, TimeUnit.DAYS);
        });

        return resultNum;
    }


    /**
     * 模板状态管理
     *
     * @param reportFormsEdit 银监模板对象
     * @return 结果
     */
    @Override
    public int updateState(ReportFormsEdit reportFormsEdit)
    {
        // 是否启用,0启用，1禁用
        if(StringUtils.isEmpty(reportFormsEdit.getReportFormNo())){
            ReportFormsEdit rfe= reportFormsEditMapper.selectReportFormsEditByPkId(reportFormsEdit.getPkId());
            reportFormsEdit.setReportFormNo(rfe.getReportFormNo());
        }

        return reportFormsEditMapper.updateReportFormsEditState(reportFormsEdit);
    }

}
